package com.wza.interview;

import org.junit.Test;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.time.Clock;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;


/**
 * <一句话功能简述>
 * <功能详细描述>
 *
 * @author Administrator
 * @version [版本号, 2018/11/16]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class TestDemo1
{
    @Test
    public void testShortInt()
    {
        short s1 = 1;
        //s1 = s1 + 1; 报错, 需显示 s1 = (short)s1 + 1;
        s1 += 1; // 隐式转换 s1 = (short)s1 + 1;
    }

    /**
     * String.intern()是一个 Native方法，它的作用是：
     * 如果【字符串常量池】中已经包含了一个等于此 String 对象的字符串，
     * 则返回代表池(运行时常量池)中这个字符串的String对象；
     * 否则，将此String对象包含的字符串添加到常量池中并且返回此String对象的引用。
     * 此方法在jdk1.6和jdk1.7中有差异
     *
     * 这段代码在jdk1.6中运行，会得到两个false，而在jdk1.7中运行会得到一个true一个false。
     *
     * 产生差异的原因是：
     * 1. 在jdk1.6中，intern()方法会把首次遇到的字符串实例复制到永久代中，返回的也是永久代中这个字符串实例的引用，
     *    而用 StringBuilder 创建的字符串实例在Java堆上，所以必然不是同一个引用，将返回false；
     *
     * 2. jdk1.7中的intern()实现【不会再复制实例】，只是在常量池中【记录首次出现的实例引用】，
     *    因此intern()返回的引用和由StringBuilder创建的那个字符串实例是同一个。
     *    对 str2 比较返回 false 是因为“java”这个字符串在执行StringBuilder.toString()之前已经出现过，
     *    字符串常量池中已经有它的引用了，不符合首次出现的原则，而“ni hao”这个字符串则是首次出现的，因此返回true。
     *
     */
    @Test
    public void testStringPosition()
    {
        String s1 = new StringBuilder("go").append("od").toString();
        System.out.println(s1.intern() == s1); // ture

        String s2 = new StringBuilder("ni").append("hao").toString();
        System.out.println(s2.intern() == s2); // ture

        String s3 = new StringBuilder("ja").append("va").toString();
        System.out.println(s3.intern() == s3); // flase, "java" 在常量池中已经存在

        String s4 = "hello";
        System.out.println(s4.intern() == s4); // true
    }

    /*
    *  1. java 程序在运行的时候, 会创建一个字符串缓冲池。
         对于诸如 String s1 ="Programming"; String s3 = "Program"; String s4 = "ming";
         这些字符串常量，程序首先会在这个 String 缓冲池中寻找相同值的对象。
         若它们在池中不存在，程序则将这些字符串常量创建于池中。
         若在池中找到了相同值得对象，则这个找到的对象的引用，就是新变量的引用。由此可见，字符串常量池中一个给定值得对象，最多只有一个。

       2. 用操作符 new 创建的字符串对象, 如 String s2 = new String("Programming");,
           或者有字符串变量、操作符'+' 参与的表达式，如 String s6 = s3 + s4;
           这样得到的引用，都要放到内存(堆heap)中保存。故，在堆中，若有几个值相同的对象，它们分别都会有各自的地址。

       3.字符串的一个成员方法 public String intern(),返回字符串对象的规范化表示形式。
         当调用 intern 方法时，如果池已经包含一个等于此 String 对象的字符串（用 equals(Object) 方法确定），
         则返回池中的字符串。否则，将此 String 对象添加到池中，并返回此 String 对象的引用。
    * */

    @Test
    public void stringEqualTest()
    {
        String s1 = "Programming";
        String s2 = new String("Programming");
        String s3 = "Program";
        String s4 = "ming";
        String s5 = "Program" + "ming";
        String s6 = s3 + s4;
        String s7 = new StringBuilder("Programming").toString();
        String s8 = new StringBuilder("Program").append("ming").toString();

        System.out.println(s1 == s2); // false
        System.out.println(s1 == s5); // true
        System.out.println(s1 == s6); // false
        System.out.println(s1 == s6.intern()); // true
        System.out.println(s2 == s2.intern()); // false
        System.out.println(s1 == s2.intern()); // true
        System.out.println(s7.intern()==s7); // false
        System.out.println(s8.intern()==s8); // false, 单独执行时为 true

        /*  编译后 class 文件的内容 :
        *   String s1 = "Programming";
            String s2 = new String("Programming");
            String s3 = "Program";
            String s4 = "ming";
            String s5 = "Programming";
            String s6 = s3 + s4;
            String s7 = "Programming";
            String s8 = "Program" + "ming";
            System.out.println(s1 == s2);
            System.out.println(s1 == s5);
            System.out.println(s1 == s6);
            System.out.println(s1 == s6.intern());
            System.out.println(s2 == s2.intern());
            System.out.println(s1 == s2.intern());
            System.out.println(s7.intern() == s7);
            System.out.println(s8.intern() == s8);
        * */
    }

    @Test
    public void testSize()
    {
        char c = '你'; // Unicode 编码, 两个字节
        System.out.println(c);
    }

    /*
    *
    * 如何实现字符串的反转及替换？
    * */
    public static String reverse(String originStr)
    {
        if (originStr == null || originStr.length() <= 0)
        {
            return originStr;
        }

        return reverse(originStr.substring(1)) + originStr.charAt(0);
    }

    @Test
    public void testReverse()
    {
        String str = "abcdefg";

        System.out.println(reverse(str));
    }

    /*
    * 将GB2312编码的字符串转换为ISO-8859-1编码的字符串
    * */

    @Test
    public void testCharSet() throws UnsupportedEncodingException
    {
        String str = "你好";

        String afterTran = new String(str.getBytes("GB2312"), "ISO-8859-1");
        System.out.println(afterTran);
    }

    /*
    * 如何取得年月日、小时分钟秒？ 
    * 如何取得从1970年1月1日0时0分0秒到现在的毫秒数？ 
    * 如何取得某月的最后一天？ 
    * 如何格式化日期？
    * */

    @Test
    public void testDate()
    {
       Calendar calendar = Calendar.getInstance();

        System.out.println(calendar.get(Calendar.YEAR));
        System.out.println(calendar.get(Calendar.MONTH));    // 0 - 11
        System.out.println(calendar.get(Calendar.DATE));
        System.out.println(calendar.get(Calendar.HOUR_OF_DAY));
        System.out.println(calendar.get(Calendar.MINUTE));
        System.out.println(calendar.get(Calendar.SECOND));

        // Java 8
        LocalDateTime dt = LocalDateTime.now();
        System.out.println(dt.getYear());
        System.out.println(dt.getMonthValue());     // 1 - 12
        System.out.println(dt.getDayOfMonth());
        System.out.println(dt.getHour());
        System.out.println(dt.getMinute());
        System.out.println(dt.getSecond());

        Calendar.getInstance().getTimeInMillis();
        System.currentTimeMillis();
        Clock.systemDefaultZone().millis(); // Java 8

        SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd");
        Date date1 = new Date();
        System.out.println(oldFormatter.format(date1));

        Calendar time = Calendar.getInstance();
        time.getActualMaximum(Calendar.DAY_OF_MONTH);

        // Java 8
        DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        LocalDate date2 = LocalDate.now();
        System.out.println(date2.format(newFormatter));
    }


    /*
    * 打印昨天的当前时刻
    * */

    @Test
    public void testYesterDayCurrent()
    {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        System.out.println(cal.getTime());


        LocalDateTime today = LocalDateTime.now();
        LocalDateTime yesterday = today.minusDays(1);

        System.out.println(yesterday);
    }
}
